﻿using System;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Security.Cryptography.X509Certificates;
using TimeProject.Engine.DbModels;

namespace TimeProject.Engine.DbContent
{
    public static class Queries
    {

        private static IQueryable<TEntity> WhereEx<TEntity>(this DbSet<TEntity> source, Expression<Func<TEntity, bool>> predicate) where TEntity : EntityBase
        {
            IQueryable<TEntity> query = source;
            query = query.Where(predicate);
            query = query.Where(x => x.IsActive);
            return query;
        }

        /// <summary>
        /// Gets the user by id.
        /// </summary>
        /// <param name="db">The db context.</param>
        /// <param name="userId">The user id.</param>
        /// <returns>The user or null if not found.</returns>
        public static User GetUser(this TimeProjectDbContext db, int userId)
        {
            return db.Users.WhereEx(x => x.Id == userId).FirstOrDefault();
        }

        /// <summary>
        /// Gets the user by username.
        /// </summary>
        /// <param name="db">The db context.</param>
        /// <param name="username">The username.</param>
        /// <returns>The user or null if not found.</returns>
        public static User GetUser(this TimeProjectDbContext db, string username)
        {
            return db.Users.WhereEx(x => x.Username == username).FirstOrDefault();
        }

        /// <summary>
        /// Gets the user's latest login.
        /// </summary>
        /// <param name="db">The db context.</param>
        /// <param name="userId">The user id.</param>
        /// <returns>The user's latest login or null if not found.</returns>
        public static UserActivity GetLatestLogin(this TimeProjectDbContext db, int userId)
        {
            return db.UserActivities.WhereEx(x => x.UserId == userId && x.Type == UserActivityType.Login)
                     .OrderByDescending(x => x.Created)
                     .Take(1)
                     .FirstOrDefault();
        }

        /// <summary>
        /// Gets the user option by key.
        /// </summary>
        /// <param name="db">The db context.</param>
        /// <param name="userId">The user id.</param>
        /// <param name="key">The option key.</param>
        /// <returns>The user option or null if not found.</returns>
        public static UserOption GetUserOption(this TimeProjectDbContext db, int userId, string key)
        {
            return db.UserOptions.WhereEx(x => x.UserId == userId && x.Key == key).FirstOrDefault();
        }

        public static OrganizationUser[] GetOrganizationUsersByUser(this TimeProjectDbContext db, int userId)
        {
            return db.OrganizationUsers.WhereEx(x => x.UserId == userId &&
                                                     x.Organization.IsActive &&
                                                     x.User.IsActive).ToArray();
        }

        public static OrganizationUser[] GetOrganizationUsersByOrganization(this TimeProjectDbContext db, int organizationId)
        {
            return db.OrganizationUsers.WhereEx(x => x.OrganizationId == organizationId &&
                                                     x.Organization.IsActive && 
                                                     x.User.IsActive).ToArray();
        }

        #region OLD
        public static User[] GetUsers(this TimeProjectDbContext db)
        {
            User[] users = db.Users.ToArray();
            return users;
        }
        #endregion
    }
}
